1 module hunt.http.session;
2 
3 import hunt.cache;
4 import hunt.utils.time;
5 
6 import std.json;
7 import std.conv;
8 import std.digest.sha;
9 import std.format;
10 import std.datetime;
11 import std.random;
12 import core.cpuid;
13 import std.string;
14 import std.experimental.logger;
15 
16 class Session
17 {
18 	private string _sessionId;
19 	private JSONValue _sessions;
20 	private SessionStorage _sessionStorage;
21 
22 	this(SessionStorage sessionStorage)
23 	{
24 		this._sessionStorage = sessionStorage;
25 		this._sessionId = _sessionStorage.generateSessionId();
26 		this._sessions = parseJSON(_sessionStorage.get(_sessionId));
27 	}
28 	this(string sessionId,SessionStorage sessionStorage)
29 	{
30 		this._sessionId = sessionId;
31 		this._sessionStorage = sessionStorage;
32 		this._sessions = parseJSON(_sessionStorage.get(_sessionId));
33 	}
34 
35 	Session set(T)(string key, T value)
36 	{
37 		_sessions[key] = value.to!string;
38 		_sessionStorage.set(_sessionId, _sessions.toString);
39 		return this;
40 	}
41 
42 	string get(string key)
43 	{
44 		try
45 		{
46 			return _sessions[key].str;
47 		}
48 		catch (Exception e)
49 		{
50 			return string.init;
51 		}
52 	}
53 
54     T get(T)(string key, T defaultValue)
55     {
56         string v = get(key);
57 
58         try
59     	{
60     		return to!T(v);
61     	}
62     	catch (Exception e)
63     	{
64     		return defaultValue;
65     	}
66     }
67 
68 	void remove(string key)
69 	{
70 		JSONValue json;
71 		
72 		foreach (string _key, ref value; _sessions)
73         {
74         	if (_key != key)
75         	{
76         		json[_key] = value;
77         	}
78         }
79 
80 		_sessions = json;
81 		_sessionStorage.set(_sessionId, _sessions.toString);
82 	}
83 
84 	string[] keys()
85 	{
86 		string[] ret;
87 		
88 		foreach (string key, value; _sessions)
89         {
90         	ret ~= key;
91         }
92         
93         return ret;
94 	}
95 
96 	string sessionId()
97 	{
98 		return _sessionId;
99 	}
100 }
101 
102 class SessionStorage
103 {
104 
105 	this(UCache cache)
106 	{
107 		_cache = cache;
108 	}
109 
110 
111 	alias set = put;
112 
113 	bool put(string key, string value, int expire)
114 	{
115 		_cache.put!string(getRealAddr(key), value, expire);
116 		return true;
117 	}
118 	
119 	bool put(string key, string value)
120 	{
121 		return put(key, value, _expire);
122 	}
123 	
124 	string get(string key)
125 	{
126 		return  cast(string)_cache.get!string(getRealAddr(key));
127 	}
128 
129 	alias isset = containsKey;
130 	bool containsKey(string key)
131 	{
132 		return _cache.containsKey(key);
133 	}
134 	
135 	alias del = erase;
136 	alias remove = erase;
137 	bool erase(string key)
138 	{
139 		return _cache.remove(getRealAddr(key));
140 	}
141 
142 
143 	string generateSessionId(string sessionName = "hunt_session")
144 	{
145 		import hunt.utils.random;
146 		SHA1 hash;
147 		hash.start();
148 		hash.put(getRandom);
149 		ubyte[20] result = hash.finish();
150 		string str = toLower(toHexString(result));
151 
152 		JSONValue json;
153 		json[sessionName] = str;
154 		json["_time"] = getCurrUnixStramp + _expire; 
155 
156 		set(str,json.toString,_expire);
157 
158 		return str;
159 	}
160 
161 
162 	void setPrefix(string prefix)
163 	{
164 		_prefix = prefix;
165 	}
166 
167 	void setExpire(int expire)
168 	{
169 		_expire = expire;
170 	}
171 
172 	string getRealAddr(string key)
173 	{
174 		return _prefix ~ key;
175 	}
176 
177 	int expire()
178 	{
179 		return _expire;
180 	}
181 
182 
183 
184 	private
185 	{
186 		string 		_prefix;
187 		string 		_sessionId;
188 
189 		int 		_expire;
190 		UCache 		_cache;
191 	}
192 }